Now that font embedding is supported in all major browsers it has become increasingly common thanks to the bulletproof embedding technique for programmers. However embedded fonts can add several milliseconds if not whole seconds and can even block rendering if not done correctly. Here you will find how to mitigate the performance implications if not eliminate them completely.
Without optimization
Font Squirrel is the place to go when you need embeddable fonts. They have a large selection of free fonts and a good font converter. For this test we will be using Josefin Slab. If you download the @font-face kit it will give you all 10 styles in 4 different formats and the css needed to make them work in all browsers. O for the day when we will just need to worry about one format, alas. As it is there is four but for simplicities sake and to target the worst offender we’ll focus on IE and its propitiatory format eot. Demo Page here.
Test results for default demo page
Load time – 2.405s
Obviously there’s room for improvement.
Remove unneeded files
10 styles is nice but way overkill. Lets condense it to 4, regular, bold, italic and bold-italic, that ought to keep all our designers happy. We could probably get rid of bold-italic but we’ll keep it just to add a challenge. It’s important to note that IE downloads every font specified in the style sheet regardless of whether it’s actually used on the page. So it will be downloading our four fonts even if there is no bolded and italicized text. New demo. Notice in the css I changed the font-family of each @font-face rule to be the same and changed the font-weight and font-style property to match to font file. This allows us to use <em> or <b> tags as we normally would without having to specify a different font-family.
Test Results: 1.340s Load time
Optimize webserver delivery
Removing all the extra styles helped a lot but that was the easy part. If you look at webpagetest’s optimization checklist it suggests doing two things to how the fonts are delivered: gzip compression and enable browser caching. The exact process for enabling gzip compression depends on which web server you are using. For the widely popular Apache it can be done in the .htaccess file. Simply add these lines:
AddType font/ttf .ttf
AddType font/otf .otf
AddType application/x-woff .woff
AddType image/svg+xml .svg
AddType application/vnd.ms-fontobject .eot
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType font/ttf "access plus 10 years"
ExpiresByType font/otf "access plus 10 years"
ExpiresByType application/vnd.ms-fontobject "access plus 10 years"
ExpiresByType application/x-woff "access plus 10 years"
ExpiresByType image/svg+xml "access plus 10 years"
</IfModule>
<IfModule mod_headers.c>
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf|eot|woff|otf|ttf|svg)$">
Header set Cache-Control "max-age=290304000, public"
</FilesMatch>
</IfModule>
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
AddOutputFilterByType DEFLATE font/ttf
AddOutputFilterByType DEFLATE font/otf
AddOutputFilterByType DEFLATE image/svg+xml
First we add the type for each font we so apache knows what to call things. Next we use either mod_expires or mod_headers to set the cache control so the browser does not need to re-download the font file. Lastly we add the DEFLATE filter to each font type so that they are compressed thanks to 7zip help. Note: we don’t add deflate to the woff font type because it is natively compressed.
It is actually possible to natively compress eot fonts using eotfast. It’s Windows only software so I had to run it in a VM but it worked. Had problems getting the GUI to work so I just used the command line. It lives up to it’s claims of reducing font sizes up to 70% and the eot files it produces are about 5-10% smaller than gzip versions of the squirrelfont generated eot files. So it’s a good idea to use it but not necessary.
Our Speed Test without eotfast now shows a load time of 0.9 s and there is still room for improvement. Notice that the repeat view load time is much lower now since we implemented caching.
Just for fun I ran the Speed Test with Eotfast which shows 0.890s load time. Wow, it loaded a whole hundredth of a second faster! (sarcasm) So if you really want to be as fast as possible use eotfast but you probably won’t notice the difference.
Embedded the Font files using mhtml
Base64 encoded data urls have long been used to save http requests for small background images and the like. They were not supported by IE until version 8 and IE8 limits them to 32 Kbs which is actually too small for some fonts. Fortunately IE6+ support a similar technology called mhtml which can be used to embed the fonts directly into our css file and save http requests. I decided to try it out to see if pages loaded any faster. It turns out they don’t.
For details on how to use mhtml see the proper mhtml syntax.
Demo page with mhtml embedded fonts.
The tests are below:
mhtml embeded font files with eotfast Load time 1.076.
mhtml embeded font files without eotfast Load time 1.044.
Besides the load time being longer this approach is very poor because the start render time is actually 1.148s because the browser doesn’t render the page until the large css file is downloaded. I thought I could get arroudn this by mhtml embedding the font files into a separate file. IE supports any file as long as it sent with a text content type. The demo page speed test has a better load time at 0.954s but it’s still longer than 0.980s. I believe this is because of several factors. First base64 encoding adds about 30% to the total file size which is mostly mitigated by using gzip compression. Also it seems IE has to work harder to decode the mhtml file because the repeat view load time is longer even though it does not have to redownload anything. The thing that really helps separate eot files load faster is that IE can download them in parallel. So the verdict is, don’t use mhtml for fonts or anything that is more than a few kilobytes.
Fonts and Start to Render Time
For the most part fonts do not affect your time to start rendering which is very good. One can safely embed fonts using the @font-face which only adds a few milliseconds to the total page load time. What most browsers do is render the entire page except the text that depends upon an external font file it will appear hidden until the file is downloaded. Except Firefox which shows a default font until the font file is loaded after which the fonts noticeably change. This behavior can be changed with the WebFont Loader which is a javascript library from Google. There is one small problem with Internet Explorer. If there are any <script> tags before the <style> tag with the @font-face it will block rendering of the entire page until the font file is downloaded. So it is always good practice to include your <script> tags just before the </head> tag or, even better, at the bottom of the page.
Font delivery networks
Gzip compression and Expire headers go a long way to help decrease the font load time but to load the fonts as fast as possible they need to be served from a superfast server. It also helps if the server is geographically close to the site visitor. This is not much different than a content delivery network, just specific to font files and the CSS to support them. There are several commercial font delivery networks, TypeFont lets you upload any font which it will then serve from their network for your site. TypeKit has a large selection of fonts which can be used from their network for the price of a subscription. Google offers their web font API which serves a limited number of fonts from Google servers. Using the service is very easy just add a line to load the css file in the <head> section:
This loads the Josefin Slab font in regular, bold, italic and bold italic. Running a speed test shows that using Google the median load time is 1.250s. What more than 350ms longer? Well if we look closely at the tests we see that my web server varies greatly in how long it takes to search pages. But if we just look at the time spent serving the fonts and css we see my server to 627 ms while google servers took 798 ms. 275 ms are spent doing DNS lookups so google’s servers are 104 ms faster. Of course this is doing a test from the same country in which my server is located. From different countries the difference would be much greater. So using Google Font API may or may not be faster than serving the files from your own server. I noticed that Google could save a DNS lookup if they served their fonts from the same domain as their CSS file. Also they are employing a User Agent test when serving the CSS file which saves a few bytes because you only send the relevant @font-face rules but User Agent aren’t always a reliable means of testing for browser capabilities. Actually Google is cheating in this case and only serves one font instead of the four font variants to IE. IE still shows bold and italic fonts but they don’t look the same as the real font files. I guess Google thinks that IE just can’t handle the extra files. It sends all four to Chrome although they are sent as ttf instead of woff. In my testing woffs are usually smaller so it would make more sense to send woff files to the browsers that support them.
Conclusion
For my own purposes I found that using embedded fonts with the above htaccess changes works very well and the performance of the page is not affected much. I much prefer to use my own server to deliver fonts where I have complete control of which fonts are servered and avoid extra DNS look ups. mhtml or data inline fonts do not increase performance. However 4 different font styles are probably not needed. 1 would actually be enough for most purposes but I choose to use 4 in these examples so that the load time of the fonts would be more predominant. Please let me know how you embed fonts in the comments below.
Well written, will definitely look at employing some of these tips in my sites.
Thanks!
Lovely post. I have been loading all formats svg, eot & iefix 🙁 ttf woff. Gotta kill ie soon!
Excellent post, really informative about this issue, well written and answers my questions perfectly. Many thanks…….
Adding the far future expires and application statements to my .htaccess made the fonts load almost instantaneously!
Thanks for the great share
🙂
Is there any reason for why image/svg+xml is not included in the ExpiresByType?
I tested out your tips and now the delay is almost non-existing. Great tip!
Is there any good way to speed up the actual rendering, or avoid that the text is blinking? I was thinking just hiding everything and when the font is rendered, show it back. This will show a blank page for a few milliseconds but thats much less annoying than all your headlines appearing after everything is rendered.
Thanks for great post!
I just over looked image/svg+xml for the expiresByType it definitely should be there. I just updated it to include it, thanks for spotting that.
Each browser implementation handles font rendering of @font-face differently. Some hide the text until the fonts loaded and some show a local font and switch after the external font is loaded. I have seen some javascript solutions to change the behavior but ultimately I think it’s better just to let the browser do whatever it’s designed to do. Changing things with javascript just seems to tricky and adds unnecessary overhead. As a general web performance rule it’s almost always better show something instead of a blank page. Visitors are much less likely to leave your page if they can tell something is happening. If it’s just a blank page they have no feedback and are likely to loose interest.
Thank you for this research, your code is excellent and I’m using it on my website.
I’m using Arial Rounded MT Bold font, downloaded as ttf and converted to eot. Both versions are on my dedicated server, I’m gzipping them and caching them, there’s no delay on IE and Chrome but the delay on FF is noticeable and irritating. It’s as if the font is still not getting cached.
But anyway, your code solved 80% of my problems, so thank you.
I’m glad I could help out. I ran into a bug that affects FF and Firebug which may be causing your delay. See https://bugzilla.mozilla.org/show_bug.cgi?id=668178 . Basically when Firebug is running it load the font twice from the server. Try disabling Firebug to see if there’s still a delay.